const fs = require('fs')
const util = require('util')



/**
 * 获取三个文件的内容 原始版本
 * 嵌套回调，形成回调地狱
 * @return {[type]} [description]
 */
 function getFilesContentV1() {
 	fs.readFile('./resouce/1.txt', (err, data1) => {
 		if(err) throw err;
 		fs.readFile('./resouce/2.txt', (err, data2) => {
 			if(err) throw err;
 			fs.readFile('./resouce/3.txt', (err, data3) => {
 				if(err) throw err;
 				var content = data1 + data2 + data3
 				console.log(content)
 			})
 		})
 	})
 }


// 通过回调函数获取异步函数的结果
// getFilesContentV2(function(rs) {
// 	console.log('-----------------------\n')
// 	console.log(rs)
// 	console.log(rs.join(''))
// });

/**
 * 过回调函数获取异步函数的结果
 * @param  {Function} callback [description]
 * @return {[type]}            [description]
 */
 function getFilesContentV2(callback) {
 	var files  = ['./resouce/1.txt', './resouce/2.txt', './resouce/3.txt'];
 	var rs = new Array()
 	for (let i = 0; i < files.length; i++) {
 		fs.readFile(files[i], (err, data) => {
 			if(err) throw err;
 			rs.push(data)
			// rs.length 作为计数器， 达到一定个数时 走回调函数
			// 相当于全部执行成功后 执行回调函数
			if(rs.length  === files.length) {
				callback(rs)
			}
		})
 	}
 }



/**
 * 采用 promise的情况
 * @return {[type]} [description]
 */
function getFilesContentV3() {
 	var files  = ['./resouce/1.txt', './resouce/2.txt', './resouce/3.txt'];

 	function getFileContent(i) {

		sleep(i * 100) // 异步任务 , 需要耗时 模拟一下
		let path = `./resouce/${i}.txt`
		return new Promise((resolve, reject) => {
			fs.readFile(path, (err, data) => {
				if(err) throw err;
				resolve(data+'')
			})
		})
	}


	// 方法1 
	let i = 1;
	let res = new Array(files.length)

	console.time('getFilesContentV3')
	getFileContent(i).then(value=> {
		res[i-1] = value
		return getFileContent(++i);
	}).then(value=> {
		res[i-1] = value
		return getFileContent(++i);
	}).then(value=> {
		res[i-1] = value
		console.log(res)
		// getFileContent: 630.188ms
		// 异步任务为串行的方式， 非并行
		console.timeEnd('getFilesContentV3') 
		console.log('-----------------------\n')
	})



}
// getFilesContentV3();
// getFilesContentV3_2();


function getFilesContentV3_2() {
	// 方法2 变成循环的方式 可以迭代
	let i = 1;
	let res = new Array(3)

	console.time('getFilesContentV3_2')
	var p = getFileContent(i)
	while(i <= 3) {
		(function(j) {
			p = p.then(value => {
				// console.log(j, value)
				res[j-1] = value
				// console.log(res)
				if(j < 3) {
					return getFileContent(j+1);
				} else {
					// 最后结束时，不能嗲用 getFileContent 
					console.log('that is over, j = ', j)
					console.log(res.join(''))
					console.timeEnd('getFilesContentV3_2') 
				}
			})
		}(i++))
	}
}

getFilesContentV4();

/**
 * async + await 用同步的方式 编写异步代码， 再也没有嵌套了
 * [getFilesContentV4 description]
 * @return {[type]} [description]
 */
async function  getFilesContentV4() {
	console.time('getFilesContentV4') 

	var data1 = await getFileContent(1);
	var data2 = await getFileContent(2);
	var data3 = await getFileContent(3);

	var res = [data1, data2, data3];
	console.log(res.join(''))
	console.timeEnd('getFilesContentV4') 
}







function sleep(ms) {
	let endTime = Date.now() + parseInt(ms) ;
	while(Date.now() <= endTime) ;
}

function getFileContent(i) {
	sleep(i * 100) // 异步任务 , 需要耗时 模拟一下
	let path = `./resouce/${i}.txt`
	// 通过 promisify 将错误优先的回调函数变为promise对象
	return util.promisify(fs.readFile)(path);
}





